﻿using System;
using System.Activities;
using System.Activities.DurableInstancing;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Text;
using AppLab.Core;
using AppLab.Data.Models;
using Wicresoft.AppFlow.Flows;

namespace Wicresoft.AppFlow.Controls
{
    public sealed class Controller
    {
        private System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);
        private Exception ex;

        #region workflow delegates
        private PersistableIdleAction WFPersistableIdle(WorkflowApplicationIdleEventArgs e)
        {
            mre.Set();
            return PersistableIdleAction.Unload;
        }
        private void WFCompleted(WorkflowApplicationCompletedEventArgs e)
        {
            mre.Set();
        }
        private UnhandledExceptionAction WFUnhandledException(WorkflowApplicationUnhandledExceptionEventArgs e)
        {
            ex = e.UnhandledException;
            mre.Set();
            return UnhandledExceptionAction.Cancel;
        }
        private void WFAborted(WorkflowApplicationAbortedEventArgs e)
        {
            ex = e.Reason;
            mre.Set();
        }
        private void WFIdel(WorkflowApplicationIdleEventArgs e)
        {
            //Console.WriteLine("Idle: Id={0}", e.InstanceId);

            //Console.WriteLine("--------BookmarkName---------------------------");
            //foreach (var item in e.Bookmarks)
            //{
            //    Console.WriteLine(" {0}", item.BookmarkName);
            //}
            //Console.WriteLine("================================");
            mre.Set();
        }
        #endregion

        #region sql instance store
        private static SqlWorkflowInstanceStore swis;
        private static SqlWorkflowInstanceStore GetInstanceStore()
        {
            if (swis == null)
                swis = new SqlWorkflowInstanceStore(GlobalConfiguration.ApplicationService);
            return swis;
        }
        #endregion

        #region workflow invokes
        public Guid ExecuteFlow(Guid fid, object e)
        {
            WorkflowApplication instance = null;

            if (fid == Guid.Empty)
                instance = new WorkflowApplication(new PackageFlow(), new Dictionary<string, object> { { "SubmitData", e } });
            else
                instance = new WorkflowApplication(new PackageFlow());


            instance.InstanceStore = GetInstanceStore();

            instance.PersistableIdle = WFPersistableIdle;
            //instance.Idle = WFIdel;
            instance.Completed = WFCompleted;
            //instance.Aborted = WFAborted;
            instance.OnUnhandledException = WFUnhandledException;

            if (fid == Guid.Empty)
                instance.Run();
            else
            {
                instance.Load(fid);
                instance.ResumeBookmark(GetFlowState(fid).ToString(), e);
            }
            mre.WaitOne();
            if (ex != null)
                throw ex;


            return instance.Id;
        }

        private FlowState GetFlowState(Guid fid)
        {
            using (var dc = PMSEntities.Create())
            {
                var e = dc.tysx_AppFlow.First(p => p.FlowID == fid);
                return (FlowState)e.tysx_FlowState.StateID;
            }
        }
        #endregion
    }
}
